
package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;

import javax.swing.AbstractListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import maquinaP.Filtro;
import maquinaP.MaquinaP;

/**
 * Interfaz de la maquinaP
 * @author Miguel Angel Diaz
 * @version 2.0
 */
public class EmuladorP extends javax.swing.JFrame {
	
    private static final long serialVersionUID = 1L;
	
	private JMenuBar jMenu;
    private JMenu jMenuArchivo;
    private JMenuItem jMenuIAbrir;
    private JMenuItem jMenuICerrar;
    private JMenuItem jMenuSalir;
    private JMenu jMenuAyuda;
    private JMenuItem jMenuIManual;
    private JLabel jLabelPila;
    private JScrollPane jScrollPila;
    private JList jListPila;
    private ListSelectionListener selListenerPila;
    private JLabel jLabelInstr;
    private JScrollPane jScrollInstr;
    private JList jListInstr;
    private ListSelectionListener selListenerInstr;
    private JLabel jLabelDatos;
    private JScrollPane jScrollDatos;
    private JList jListDatos;
    private ListSelectionListener selListenerDatos;
    private JLabel jLabelDin;
    private JScrollPane jScrollDin;
    private JList jListDin;
    private ListSelectionListener selListenerDin;
    private JButton jButtonTodo;
    private JButton jButtonPasos;
    private JButton jButtonReini;
    private JTextField jTextInfor;
    private JLabel jLabelB;
    private JTextField jTextFieldB;
    private JLabel jLabelC;
    private JTextField jTextFieldC;
    private JLabel jLabelCP;
    private JTextField jTextFieldCP;
    private JLabel jLabelF;
    private JTextField jTextFieldF;
    private JLabel jLabelH;
    private JTextField jTextFieldH;
    
    /**
	 * MaquinaP sobre la que se ejecutan los programas en codigoP .
	 */
	private MaquinaP mp;
	
	/**
	 * Filas que se muestran en la pila.
	 */
	private int filasPila;
	
	/**
	 * Titulo de la ventana
	 */
	private String TITULO_VENTANA = "Emulador MaquinaP 2.0";

    /** 
     * Crea un nuevo formulario EmuladorP.
     */
    public EmuladorP() {
    	creaVentana();
        filasPila = jListPila.getVisibleRowCount();
        actualiza();
    }

    /**
     * Crea un nuevo formulario EmuladorP con el archivo especificado por ruta cargado.
     * @param ruta Ruta del archivo a cargar.
     */
    public EmuladorP(String ruta) {
    	creaVentana();
    	filasPila = jListPila.getVisibleRowCount();
        mp.cargarPrograma(ruta);
    	if (mp.programaCargado())
    		setTitle(TITULO_VENTANA + " - " + new File(ruta).getName());
    	actualiza();	
     }
    
    /**
     * Crea todos los componentes de la ventana.
     */
    private void creaVentana(){    	
    	mp = new MaquinaP();        
        inicializaComponentes();
        setTitle(TITULO_VENTANA);
        
        // Centrar ventana en pantalla
        try {
            Dimension ventana = Toolkit.getDefaultToolkit().getScreenSize();
            this.setLocation(ventana.width/2-this.getWidth()/2, ventana.height/2-this.getHeight()/2);
        } catch (Exception e) {
            this.setLocation(0,0);
        }
        
        setVisible(true);
    }
    
    /**
     * Actualiza los componentes de la ventana.
     */
    private void actualiza(){
    	
        // Actualiza la pila
        ArrayList<String> pila = new ArrayList<String>();
        for (int i=0; i<(filasPila-mp.getPila().size()); i++)
            pila.add(" ");
        for (int i=mp.getPila().size()-1; i>=0; i--)
            pila.add(i + "@  " + mp.getPila().get(i).toString());
        jListPila.setListData(pila.toArray());
        actualizaSeleccionPila();
            
        // Actualiza la memoria de instrucciones
        ArrayList<String> mInstr = new ArrayList<String>();
        for (int i=0; i<mp.getMInstr().size(); i++)
        	mInstr.add(i + "@  " + mp.getPosMInstr(i));
        jListInstr.setListData(mInstr.toArray());
        actualizaSeleccionInstr();
        
        // Actualiza la memoria de datos
        ArrayList<String> mDatos = new ArrayList<String>();
        for (int i=0; i<MaquinaP.INICIO_MEM_DINAMICA; i++)
        	if (mp.getPosMDatos(i) != Integer.MIN_VALUE)
        		mDatos.add(i + "@  " + mp.getPosMDatos(i));
        	else
        		mDatos.add(i + "@");
        jListDatos.setListData(mDatos.toArray());
        actualizaSeleccionDatos();
        
        // Actualiza la memoria dinamica
        ArrayList<String> mDin = new ArrayList<String>();
        for (int i=MaquinaP.INICIO_MEM_DINAMICA; i<mp.getMDatos().length; i++)
        	if (mp.getPosMDatos(i) != Integer.MIN_VALUE)
        		mDin.add(i + "@  " + mp.getPosMDatos(i));
        	else
        		mDin.add(i + "@");
        jListDin.setListData(mDin.toArray());
        actualizaSeleccionDin();
        
        // Actualiza el registro B
        jTextFieldB.setText(Integer.toString(mp.getB()));
        
        // Actualiza el registro C
        jTextFieldC.setText(Integer.toString(mp.getC()));
        
        // Actualiza el estado
        jTextFieldF.setText(mp.getF()+"");
        
        // Actualiza el registro H
        jTextFieldH.setText(mp.getH()+"");
        
        // Actualiza el contador de programa
        jTextFieldCP.setText(Integer.toString(mp.getCP()));
        
        // Actualiza el mensaje de informacion
        jTextInfor.setText(mp.getInfo());
    	if (mp.getF() == 'e')
    		jTextInfor.setForeground(Color.red);
        else if (mp.getF() == 's')
        	jTextInfor.setForeground(Color.blue);
        else
        	jTextInfor.setForeground(Color.black);
    	
    	// Actualiza el estado de los botones
    	if (!mp.programaCargado()){
    		jButtonTodo.setEnabled(false);
    		jButtonPasos.setEnabled(false);
    		jButtonReini.setEnabled(false);
    	}
    	else {
    		if (mp.getF()!='r'){
    			jButtonTodo.setEnabled(false);
        		jButtonPasos.setEnabled(false);
        	}
    		else {
	    		jButtonTodo.setEnabled(true);
	    		jButtonPasos.setEnabled(true);
    		}
    		jButtonReini.setEnabled(true);
    	}
    	
    }
    
    /** 
     * Este metodo lo llama el constructor para inicializar la vista.
     */
    private void inicializaComponentes() {

        jScrollPila = new JScrollPane();
        jListPila = new JList();
        jLabelPila = new JLabel();
        jButtonPasos = new JButton();
        jTextInfor = new JTextField();
        jButtonTodo = new JButton();
        jButtonReini = new JButton();
        jScrollInstr = new JScrollPane();
        jListInstr = new JList();
        jLabelInstr = new JLabel();
        jScrollDatos = new JScrollPane();
        jListDatos = new JList();
        jScrollDin = new JScrollPane();
        jListDin = new JList();
        jLabelDatos = new JLabel();
        jLabelDin = new JLabel();
        jTextFieldB = new JTextField();
        jLabelB = new JLabel();
        jTextFieldC = new JTextField();
        jLabelC = new JLabel();
        jTextFieldF = new JTextField();
        jLabelF = new JLabel();
        jTextFieldH = new JTextField();
        jLabelH = new JLabel();
        jTextFieldCP = new JTextField();
        jLabelCP = new JLabel();
        jMenu = new JMenuBar();
        jMenuArchivo = new JMenu();
        jMenuIAbrir = new JMenuItem();
        jMenuICerrar = new JMenuItem();
        jMenuSalir = new JMenuItem();
        jMenuAyuda = new JMenu();
        jMenuIManual = new JMenuItem();

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setBounds(new java.awt.Rectangle(0, 0, 514, 452));
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                oyenteRedimensionarForm(evt);
            }
        });

        jMenuArchivo.setText("Archivo");

        jMenuIAbrir.setText("Abrir");
        jMenuIAbrir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                oyenteJMenuIAbrir(evt);
            }
        });
        jMenuArchivo.add(jMenuIAbrir);

        jMenuICerrar.setText("Cerrar");
        jMenuICerrar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                oyenteJMenuICerrar(evt);
            }
        });
        jMenuArchivo.add(jMenuICerrar);

        jMenuSalir.setText("Salir");
        jMenuSalir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                oyenteJMenuISalir(evt);
            }
        });
        jMenuArchivo.add(jMenuSalir);

        jMenu.add(jMenuArchivo);

        jMenuAyuda.setText("Ayuda");

        jMenuIManual.setText("Manual");
        jMenuIManual.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                oyenteJMenuIManual(evt);
            }
        });
        jMenuAyuda.add(jMenuIManual);

        jMenu.add(jMenuAyuda);

        setJMenuBar(jMenu);

        jLabelPila.setText("Pila de Operandos");
        jListPila.setModel(new AbstractListModel() {
            private static final long serialVersionUID = 1L;
			String[] strings = {};
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPila.setViewportView(jListPila);
        jListPila.setToolTipText("Contiene los operandos");
        selListenerPila = new javax.swing.event.ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e) {
				actualizaSeleccionPila();
			}
        };
        jListPila.addListSelectionListener(selListenerPila);
        
        jLabelInstr.setText("Memoria de Instrucciones");
        jListInstr.setModel(new AbstractListModel() {
            private static final long serialVersionUID = 1L;
			String[] strings = {};
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollInstr.setViewportView(jListInstr);
        jListInstr.setToolTipText("Programa cargado en memoria");
        selListenerInstr = new javax.swing.event.ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e) {
				actualizaSeleccionInstr();
			}
        };
        jListInstr.addListSelectionListener(selListenerInstr);
        
        jLabelDatos.setText("Memoria de Datos");
        jListDatos.setModel(new AbstractListModel() {
            private static final long serialVersionUID = 1L;
			String[] strings = {};
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollDatos.setViewportView(jListDatos);
        jListDatos.setToolTipText("Parte de la memoria correspondiente a datos (" + 0 + "," + (MaquinaP.INICIO_MEM_DINAMICA-1) + ")");
        selListenerDatos = new javax.swing.event.ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e) {
				actualizaSeleccionDatos();
			}
        };
        jListDatos.addListSelectionListener(selListenerDatos);
        
        jLabelDin.setText("Memoria Dinamica");
        jListDin.setModel(new AbstractListModel() {
            private static final long serialVersionUID = 1L;
			String[] strings = {};
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollDin.setViewportView(jListDin);
        jListDin.setToolTipText("Parte de la memoria correspondiente a memoria dinamica (" + MaquinaP.INICIO_MEM_DINAMICA + "," + (mp.getMDatos().length-1) + ")");
        jListDin.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        selListenerDin = new javax.swing.event.ListSelectionListener(){
			public void valueChanged(ListSelectionEvent e) {
				actualizaSeleccionDin();
			}
        };
        jListDin.addListSelectionListener(selListenerDin);
        
        jButtonTodo.setText("Ejecutar todo");
        jButtonTodo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                oyenteJButtonTodo(evt);
            }
        });
        jButtonTodo.setToolTipText("Ejecuta el programa completo");

        jButtonPasos.setText("Ejecutar por pasos");
        jButtonPasos.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                oyenteJButtonPasos(evt);
            }
        });
        jButtonPasos.setToolTipText("Ejecuta las instrucciones una a una");

        jButtonReini.setText("Reiniciar");
        jButtonReini.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                oyenteJButtonReini(evt);
            }
        });
        jButtonReini.setToolTipText("Resetea la ejecucion");

        jTextInfor.setEditable(false);
        jTextInfor.setToolTipText("Informacion sobre la ejecucion");

        jLabelB.setText("Registro B");
        jTextFieldB.setHorizontalAlignment(JTextField.CENTER);
        jTextFieldB.setEditable(false);
        jTextFieldB.setToolTipText("Base del registro de activacion activo");
        
        jLabelC.setText("Registro C");
        jTextFieldC.setHorizontalAlignment(JTextField.CENTER);
        jTextFieldC.setEditable(false);
        jTextFieldC.setToolTipText("Cima pila registros de activacion");

        jLabelF.setText("Registro F");
        jTextFieldF.setHorizontalAlignment(JTextField.CENTER);
        jTextFieldF.setEditable(false);
        jTextFieldF.setToolTipText("Estado: 'r'=ejecutando, 's'=parado, 'e'=error");

        jLabelH.setText("Registro H");
        jTextFieldH.setHorizontalAlignment(JTextField.CENTER);
        jTextFieldH.setEditable(false);
        jTextFieldH.setToolTipText("Primera posicion libre de memoria dinamica");

        jLabelCP.setText("CP");
        jTextFieldCP.setHorizontalAlignment(JTextField.CENTER);
        jTextFieldCP.setEditable(false);
        jTextFieldCP.setToolTipText("Contador de programa");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jTextInfor, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 514, Short.MAX_VALUE)
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jScrollPila, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 127, Short.MAX_VALUE)
                            .add(jLabelPila))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jLabelInstr)
                            .add(jScrollInstr, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 274, Short.MAX_VALUE))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jLabelDatos)
                            .add(jLabelDin)
                            .add(jScrollDatos, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE)
                            .add(jScrollDin, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE))
                        .add(37, 37, 37)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                .add(jLabelB)
                                .add(jTextFieldB, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                .add(jLabelC)
                                .add(jTextFieldC, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                .add(jLabelF)
                                .add(jTextFieldF, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                .add(jLabelH)
                                .add(jTextFieldH, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                .add(jLabelCP)
                                .add(jTextFieldCP, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(jButtonTodo, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jButtonPasos, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jButtonReini, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .addContainerGap()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(layout.createSequentialGroup()
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                    .add(jLabelPila)
                                    .add(jLabelInstr))
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(jScrollInstr, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 286, Short.MAX_VALUE)
                                    .add(jScrollPila, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 286, Short.MAX_VALUE)))
                            .add(layout.createSequentialGroup()
                                .add(jLabelDatos)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(jScrollDatos, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 130, Short.MAX_VALUE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(jLabelDin)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(jScrollDin)))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(jButtonReini)
                            .add(jButtonTodo)
                            .add(jButtonPasos)))
                    .add(layout.createSequentialGroup()
                        .add(42, 42, 42)
                        .add(jLabelB)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jTextFieldB, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jLabelC)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jTextFieldC, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jLabelF)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jTextFieldF, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jLabelH)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jTextFieldH, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jLabelCP)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jTextFieldCP, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jTextInfor, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
        
    }

    /**
     * Metodo encargado de manejar el evento generado por la redimension del formulario.
     * @param evt Evento a capturar.
     */
    private void oyenteRedimensionarForm(java.awt.event.ComponentEvent evt) {
		if (getWidth()<514)
	        setSize(514,getHeight());
	    if (getHeight()<452)
	    	setSize(getWidth(), 452);
	    filasPila = jScrollPila.getHeight()/18;
	    actualiza();
	}
    
    /**
     * Metodo encargado de seleccionar en la pila la posicion siguiente a la cima (la primera libre) y 
     * de que no se pueda cambiar dicha seleccion.
     */
    private void actualizaSeleccionPila(){
    	jListPila.removeListSelectionListener(selListenerPila);
    	int select = filasPila-1 - mp.getPila().size();
    	jListPila.setSelectedIndex(select);
    	jListPila.ensureIndexIsVisible(select);
    	jListPila.addListSelectionListener(selListenerPila);
    }
	
    /**
     * Metodo encargado de seleccionar en la memoria de intrucciones la posicion a la que apunta el 
     * contador de programa y de que no se pueda cambiar dicha seleccion.
     */
    private void actualizaSeleccionInstr(){
    	jListInstr.removeListSelectionListener(selListenerInstr);
    	int select = mp.getCP();
    	jListInstr.setSelectedIndex(select);
        jListInstr.ensureIndexIsVisible(select);
        jListInstr.addListSelectionListener(selListenerInstr);
    }
	
    /**
     * Metodo encargado de seleccionar en la memoria de datos las posiciones a las que apuntan
     * el registro B y el registro C, y de que no se pueda cambiar dicha seleccion.
     */
    private void actualizaSeleccionDatos(){
    	jListDatos.removeListSelectionListener(selListenerDatos);
    	int[] select = {mp.getB(), mp.getC()};
        jListDatos.setSelectedIndices(select);
        jListDatos.ensureIndexIsVisible(select[0]);
        jListDatos.ensureIndexIsVisible(select[1]);
        jListDatos.addListSelectionListener(selListenerDatos);
    }
   
    /**
     * Metodo encargado de seleccionar en la memoria dinamica la posicion a la que apunta el 
     * registro H y de que no se pueda cambiar dicha seleccion.
     */
    private void actualizaSeleccionDin(){
    	jListDin.removeListSelectionListener(selListenerDin);
    	int select = mp.getH() - MaquinaP.INICIO_MEM_DINAMICA;
    	jListDin.setSelectedIndex(select);
        jListDin.ensureIndexIsVisible(select);
        jListDin.addListSelectionListener(selListenerDin);
    }
	
    /**
     * Metodo encargado de manejar el evento generado por la pulsacion del boton Ejecutar todo.
     * @param evt Evento a capturar.
     */
    private void oyenteJButtonTodo(ActionEvent evt) {
    	if (mp.programaCargado()){
        	mp.ejecutaPrograma();
        	actualiza();
        }
    }
	
    /**
     * Metodo encargado de manejar el evento generado por la pulsacion del boton Ejecutar por pasos.
     * @param evt Evento a capturar.
     */
    private void oyenteJButtonPasos(ActionEvent evt) {
    	if (mp.programaCargado()){
        	mp.ejecutaInstruccion();
        	actualiza();
        }
    }
	
	/**
     * Metodo encargado de manejar el evento generado por la pulsacion del boton Reiniciar.
     * @param evt Evento a capturar.
     */
    private void oyenteJButtonReini(ActionEvent evt) {
    	mp.reinicia();
        actualiza();
    }

    /**
     * Metodo encargado de manejar el evento generado por la pulsacion sobre la opcion del menu Abrir.
     * @param evt Evento a capturar.
     */
    private void oyenteJMenuIAbrir(ActionEvent evt) {
    	JFileChooser jFileChooser= new JFileChooser();
        jFileChooser.setCurrentDirectory(new File(rutaTrabajo()));
        jFileChooser.setMultiSelectionEnabled(false);
        jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        jFileChooser.setFileFilter(new Filtro());
        int opt = jFileChooser.showOpenDialog(this);
        try {
        	if (opt != JFileChooser.CANCEL_OPTION){
	        	String fichero = jFileChooser.getSelectedFile().getPath();
	            mp.reinicia();
	            mp.cargarPrograma(fichero);
	            if (mp.programaCargado())
	            	setTitle(TITULO_VENTANA + " - " + jFileChooser.getSelectedFile().getName());
        	}
        }
        catch (Exception e){
        	mp = new MaquinaP();
        	JOptionPane.showMessageDialog(this, "Se produjo un error al leer el archivo.", "Error", JOptionPane.ERROR_MESSAGE);
        }
        filasPila = jScrollPila.getHeight()/18;
        actualiza();
    }
    
    /**
	 * Devuelve la ruta del directorio raiz de la aplicacion 
	 * @return ruta de la carpeta
	 */
	private String rutaTrabajo(){
		String ruta = System.getProperty("java.class.path");
		String separadorRutas = System.getProperty("path.separator");
		// Distinguir entre ejecucion desde eclipse y ejecucion desde el jar
		if (ruta.contains(separadorRutas))
			ruta = ruta.substring(0,ruta.indexOf(separadorRutas)-4);
		else {
			int longJar = ruta.length()-ruta.lastIndexOf(System.getProperty("file.separator"));
			ruta = ruta.substring(0, ruta.length()-longJar);
		}
		return ruta;
	}
	
    /**
     * Metodo encargado de manejar el evento generado por la pulsacion sobre la opcion del menu Cerrar.
     * @param evt Evento a capturar.
     */
    private void oyenteJMenuICerrar(java.awt.event.ActionEvent evt) {
		mp = new MaquinaP();
		setTitle(TITULO_VENTANA);
		actualiza();
	}
	
	/**
     * Metodo encargado de manejar el evento generado por la pulsacion sobre la opcion del menu Salir.
     * @param evt Evento a capturar.
     */
    private void oyenteJMenuISalir(ActionEvent evt) {
    	dispose();
    }
	
    /**
     * Metodo encargado de manejar el evento generado por la pulsacion sobre la opcion del menu Manual.
     * @param evt Evento a capturar.
     */
    private void oyenteJMenuIManual(ActionEvent evt) {
    	try{
            BufferedReader flujo = new BufferedReader(new FileReader(rutaTrabajo()+File.separator+"Manual.txt"));
            String frase = flujo.readLine();
            String mensaje = "";
            while(frase != null){
                mensaje += frase+"\n";
                frase = flujo.readLine();
            }
            new Ventana(mensaje, this);
        }
        catch(Exception e){
        	JOptionPane.showMessageDialog(this, "Archivo \"Manual.txt\" no encontrado", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }
	
}
